/** @description     */

// 递归函数
function sortTree(nodes,sortField) {
  return nodes
    .sort((a, b) => {
      const a_level = a[sortField] + '' // number转string
      const b_level = b[sortField] + '' // number转string
      if (a_level.includes('-') && b_level.includes('-')) {
        // pop()是取数组的最后一个元素，但是会删除其它元素，影响原来数组，
        // 所以这里要进行浅拷贝
        const a_num = Number([...a_level.split('-')].pop())
        const b_num = Number([...b_level.split('-')].pop())
        return a_num - b_num
      }
      return -1
    })
    .map((node) => ({
      ...node,
      children: node.children ? sortTree(node.children, sortField) : undefined,
    }))
}

// 将按钮操作权限，插入到对应的菜单（新增）节点action下
async function insert_actions(actions, menus) {
  return new Promise((reslove) => {
    // action.menu_id 和 menus.id 找匹配
    for (const action of actions) {
      // item：通过item的'parent_id'属性，找到它的爸爸 parentObj
      const menuObj = menus.find((findMenu) => findMenu.id == action.menu_id)

      if (!menuObj) continue //理论不存在找不到，因为操作权限的存在都是跟菜单挂钩的

      //爸爸 parentObj，添加儿子item
      if (!menuObj.actions) menuObj.actions = []
      menuObj.actions.push(action)
    }
    // console.log('新的menus～～')
    // console.log(JSON.stringify(menus))
    reslove(menus)
  })
}

/** 
 * @description 一个对象数组，按照对象的某个属性进行排序
 * @param actions 操作权限列表
 * @param items 菜单列表
 * @param group_sort_Field 按哪个字段组合、排序
*/
function format_menuListData(actions ,items, group_sort_Field) {

  // 将操作权限，加入到各菜单
  if(actions.length > 0) {
    insert_actions(actions ,items)
  }

  // 1、将数据按照parent_id的父子级关系，重新组合
  for (const item of items) {
    // 给children = null，赋值空数组
    if (!item.children || item.children.length == 0) {
      item.children = []
    }
    
    // 说明没有'-',也就是一级菜单的意思
    if (item[group_sort_Field].split('-').length != 1) {
      // item：非一级菜单；通过item的'parent_id'属性，找到它的爸爸 parentObj
      const parentObj = items.find((findItem) => findItem.id == item.parent_id)
      //爸爸 parentObj，添加儿子item
      if (!parentObj) continue
      parentObj.children.push(item)
    }
  }

  //  到此第一次for循环结束，可以得到一个总数不变的items数组，
  //  但是所有type为1的元素，内部的children都已经装载完毕，包括儿子的children也装载完成！
  // console.log('第1步完成')

  // 2、把数组里第一层元素，level不是1的都去掉
  let itemsCopy = [...items]
  for (const item of items) {
    if (item[group_sort_Field].split('-').length != 1) {
      itemsCopy = itemsCopy.filter((value) => value != item)
    }
  }
  // console.log('第2步完成')

  // 第3步、递归排序，按照level
  const sortedData = sortTree([...itemsCopy], group_sort_Field)

  // 第4步、虽然里面排序正常； 但是一级菜单的顺序不对
  // 对一级菜单进行排序
  sortedData.sort((a, b) => a[group_sort_Field] - b[group_sort_Field])
  // console.log('\n\n第3步完成')
  // console.log(JSON.stringify(sortedData))
  return sortedData
}

/** 注意：此方向只能做到父、子两级排序，更深入的需要直接用‘递归’实现
 * @description 对象数组，删掉某个对象后，按照某个字段重新排序（比如5-2-1，5-2-2）
 * @param {已经删除后的数据源} data 
 * @param {要删除的数据} deleteObj 
 * @param {按照哪个字段排序} sortProps 
 * @param {哪个字段表示上一级} parentProps 
 * * @param {sortProps是按照什么进行连接的} joinChar 
 */
function sortUpdate (data, deleteObjs, sortProps, parentProps='parent_id', joinChar='-') {
  
  data.forEach(element => {
      // console.log('\n\n************')
      // console.log('本次要比较的是：' + JSON.stringify(element))
      
      // 1、先创建一个临时变量 'k_index'，并复制sortPros的值
      element['k_index'] = element[sortProps]
      // console.log('打印添加临时变量后的element：' + JSON.stringify(element))
      
      // 2、遍历要删除的object元素
      deleteObjs.forEach((deleteObj, index) => {
        // console.log('\n第' + index + '次要删除的是～～～～·：' + JSON.stringify(deleteObj))
        
        // 2.1、拿到deleteObj的索引，deleteObj.level是'5-2-3'，那就拿到最后这个‘3’
        const delete_level = deleteObj[sortProps] //level
        const delete_index = delete_level.split(joinChar).slice(-1)[0]

        // 2.2、拿到当前element的索引，跟deleteObj的索引进行比较
        if(element[parentProps]&& element[parentProps] &&
          element[parentProps] == deleteObj[parentProps]){ //说明是同一级别
          // console.log('\n')
          // console.log('找到了同级别：' + JSON.stringify(element))

          // 按照参数joinChar字符，进行分组
          const k_element_split = element['k_index'].split(joinChar)
          
          // 拿到最后一个序号3
          let k_emement_index = k_element_split.slice(-1)[0]

          // console.log(`同级别的index是：${k_emement_index}   要删除的index是：${delete_index}`)

          // 如果element的序号大于要删除的序号，则序号减去1
          if(k_emement_index > delete_index) {
              // 比如 '5-2-3'，element_split最终变为数组  [5,2,3]
              const element_split = element[sortProps].split(joinChar)
              
              // emement_index 变为 3
              let emement_index = element_split.slice(-1)[0] //拿到最后一个序号
              
              // 因为element的序号，大于deleteObj的序号，所以element的序号要减去1
              emement_index--

              // 拿到 [5,2]
              let begin = element_split.slice(0, element_split.length - 1) //除最后一个，都要
              // 拼成 '5-2'   （中间的拼接字符由joinChar决定）
              begin = begin.join(joinChar) // ‘-’ 拼接

              // 更新element序号
              element[sortProps] =  begin + joinChar + emement_index
              // console.log(`更新后的element：${JSON.stringify(element)}`)
          } else {
              // console.log('index偏小，下一个！')
          }
        }
      });

      // 3、去掉临时属性'k_index'
      delete element.k_index
  });
  return data
}

/**
 * 数据 -》字符串
 * @param {any} val 需要处理的数据
 * @param {string} defaultValue 如果val内容为空，要返回的值，默认返回空字符串
 * @param {string} consoleMsg 在val内容为空的，控制台可以打印一些提示内容
 * @returns 返回处理过后的数据
 */
function JSSToString(val, defaultValue = '', consoleMsg = null) {
  if(val == null || val === undefined) {
    console.log('\n********************')
    // console.log('@JSSToString：噢呦，内容为空～～')
    console.error(('@JSSToString：噢呦，内容为空～～'))
    if(consoleMsg) console.log(consoleMsg)
    console.log('********************\n')
    return defaultValue
  } 
  val = val.toString()
  return val.toString()
}


/**
 * 原数组元素顺序不变的情况下，给数组的元素们添加一个序号字段，格式：'1'、'1-1'、'1-2-1'
 * @param {Array} data 原数组
 * @param {string} childrenProp 如果有子集，哪个字段名存放子集们
 * @param {string} sortProps 新添加的序号，绑定到哪个属性上（属性名字）
 * @returns 
 */
function sortDefault(data, childrenProp, sortProps) {
  // 1、类型校验
  if (!Array.isArray(data)) return 'data必须是数组'

  if ((typeof childrenProp) !== 'string') return 'childrenProp必须是字符串'
  
  if ((typeof sortProps) !== 'string') return 'sortProps必须是字符串'
  
  if (!Array.isArray(data)) return 'data必须是数组类型'
  
  // 定义递归函数
  function exp(items, prefix) {
    items.forEach((element, index) => {
      // 2.1、对element排序
      if(prefix == '') {
        element[sortProps] = index + 1 + ''
      } else {
        element[sortProps] = prefix + '-' + Number(index + 1)
      }

      // 2.2、如果有子集，那就递归
      if (element[childrenProp] && element[childrenProp].length > 0) {
        exp(element[childrenProp], element[sortProps])
      }
    });
  }
  
  // 2、对原数组 - 浅拷贝
  const dataCopy = [...data]
  exp(dataCopy, '')
  
  // 3、返回最终数组
  return dataCopy
}

/**
 * 数组对象，按照对象的children属性拆分开
 * @param {any[]} nodes 
 * @returns {any[]}
 */
function flattenTree(nodes) {
  const result = []

  function flatten(nodes, parentValue = null) {
    nodes.forEach((node) => {
      const newNode = {
        ...node,
        value: `${parentValue ? parentValue + ':' : ''}${node.value}`,
      }
      result.push(newNode)
      if (node.children) {
        flatten(node.children, newNode.value)
      }
    })
  }

  flatten(nodes)
  return result
}

module.exports = { format_menuListData, sortUpdate, JSSToString, sortDefault, flattenTree }


/**
 *  sortUpdate - 测试案例
 
// 引入函数
const { sortUpdate } = require('./routes/menu/jss_math')

function go() {
  // 删除后的数据源
  let data = [
    {
        "id": 10039, 
        "menu_name": "舞设1", 
        "tag": "/other/my-diary/dance/dance-she/she-1", 
        "parent_id": 10035, 
        "url": null, 
        "children": null, 
        "permissions_role_ids": "1、3、17", 
        "menu_type": "5-2-3-1-1", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-09T00:09:44.000Z", 
        "update_time": "2024-05-10T00:35:06.000Z"
    }, 
    {
        "id": 10043, 
        "menu_name": "舞设2", 
        "tag": "/other/my-diary/dance/dance-she/she-2", 
        "parent_id": 10035, 
        "url": null, 
        "children": null, 
        "permissions_role_ids": "1、17", 
        "menu_type": "5-2-3-1-2", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-10T00:18:18.000Z", 
        "update_time": "2024-05-10T00:29:07.000Z"
    }, 
    {
        "id": 10047, 
        "menu_name": "舞设4", 
        "tag": "/other/my-diary/dance/dance-she/she-4", 
        "parent_id": 10035, 
        "url": null, 
        "children": null, 
        "permissions_role_ids": "1、17", 
        "menu_type": "5-2-3-1-4", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-10T00:18:18.000Z", 
        "update_time": "2024-05-10T00:44:28.000Z"
    }, 
    {
        "id": 10050, 
        "menu_name": "舞设6", 
        "tag": "/other/my-diary/dance/dance-she/she-6", 
        "parent_id": 10035, 
        "url": null, 
        "children": null, 
        "permissions_role_ids": "", 
        "menu_type": "5-2-3-1-6", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-10T00:42:50.000Z", 
        "update_time": "2024-05-10T00:44:33.000Z"
    }
  ]
  // 删除了哪些
  const delete_objs = [
    {
        "id": 10044, 
        "menu_name": "舞设3", 
        "tag": "/other/my-diary/dance/dance-she/she-3", 
        "parent_id": 10035, 
        "url": null, 
        "children": [ ], 
        "permissions_role_ids": [
            0
        ], 
        "menu_type": "5-2-3-1-3", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-10T00:42:50.000Z", 
        "update_time": "2024-05-10T00:45:25.000Z"
    }, 
    {
        "id": 10049, 
        "menu_name": "舞设5", 
        "tag": "/other/my-diary/dance/dance-she/she-5", 
        "parent_id": 10035, 
        "url": null, 
        "children": [ ], 
        "permissions_role_ids": [
            1, 
            17
        ], 
        "menu_type": "5-2-3-1-5", 
        "icon_url": null, 
        "icon_native": null, 
        "create_time": "2024-05-10T00:18:18.000Z", 
        "update_time": "2024-05-10T00:45:21.000Z"
    }
  ]
  // 开始调用
  const last_data = sortUpdate([...data], delete_objs, 'menu_type', 'parent_id', '-')
  console.log('\n打印最终 delete_objs----')
  console.log(last_data)
}

go()

 */


// const data = [
//   { id: 10001, title: '首页', type: 1, level: '1', parent_id: 0, children: [] },
//   { id: 10002, title: '个人中心', type: 1, level: '3', parent_id: 0, children: [] },
//   { id: 10003, title: '体育模块', type: 1, level: '2', parent_id: 0, children: [] },
//   { id: 10004, title: '我的详情', type: 2, level: '3-1', parent_id: 10002, children: [] },
//   { id: 10005, title: '直播模块', type: 2, level: '1-1', parent_id: 10001, children: [] },
//   { id: 10006, title: '直播室', type: 3, level: '1-1-1', parent_id: 10005, children: [] },
//   { id: 10007, title: '新闻模块', type: 1, level: '4', parent_id: 0, children: [] },
//   { id: 10008, title: '最新快报', type: 2, level: '4-1', parent_id: 10007, children: [] },
//   { id: 10009, title: '文章详情', type: 3, level: '4-1-3', parent_id: 10008, children: [] },
//   { id: 10010, title: '作者介绍', type: 3, level: '4-1-1', parent_id: 10008, children: [] },
//   { id: 10010, title: '文章背景', type: 3, level: '4-1-2', parent_id: 10008, children: [] },
// ]

//  排序后应该这样：
// 首页 ｜ 直播模块 ｜ 直播室
// 个人中心 ｜我的详情
// 体育模块
// 新闻模块 ｜ 最新快报 ｜ 文章详情、作者介绍、文章背景


// TODO: 测试 - sortDefault方法
/** 
  * 测试 - sortDefault方法


const data = [
  {
    id: 1001,
    type: '5',
    children: [
      {
        id: 1319,
        type: '5-3',
        children: [
          { id: 1322, type: '5-3-1'},
          { id: 1321, type: '5-3-3'},
          { id: 1328, type: '5-3-4'},
          { id: 1389, type: '5-3-2'},
        ]
      },
      {
        id: 1109,
        type: '5-1',
        children: [
          { id: 1110, type: '5-1-1'},
          { id: 1119, type: '5-1-2'},
          { id: 1207, type: '5-1-4'},
          { id: 1179, type: '5-1-3'},
        ]
      },
      {
        id: 1129,
        type: '5-2',
        children: [
          { id: 1110, type: '5-2-1'},
          { id: 1119, type: '5-2-3'},
          { id: 1207, type: '5-2-4'},
          { id: 1179, type: '5-2-2'},
        ]
      }
    ],
  },
  { id: 1009, type: '5-3' },
  { id: 1007, type: '5-2' },
  {
    id: 1003,
    type: '5-1',
    children: [ 
      { id: 1233, type: '5-3' },
    ]
  },
  { id: 1002, type: '2' },
  { id: 1005, type: '2' }
]
//  调用
const { sortDefault } = require('./routes/menu/jss_math');
const data_after = sortDefault(data, 'children', 'sortid')
console.log('排序后1 ', JSON.stringify(data_after))
*/